package com.seeyon.ctp.rest.resources;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.logging.Log;

import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.kk.util.HeheHttpUtil;
import com.seeyon.apps.kk.util.RestUtil;
import com.seeyon.apps.kk.vo.OrcVo;
import com.seeyon.cap4.form.bean.FormBean;
import com.seeyon.cap4.form.bean.FormDataMasterBean;
import com.seeyon.cap4.form.bean.FormDataSubBean;
import com.seeyon.cap4.form.bean.FormFieldBean;
import com.seeyon.cap4.form.bean.FormFieldComEnum;
import com.seeyon.cap4.form.bean.FormTableBean;
import com.seeyon.cap4.form.bean.fieldCtrl.FormFieldCtrl;
import com.seeyon.cap4.form.bean.fieldCtrl.utils.ImgUtil;
import com.seeyon.cap4.form.service.CAP4FormManager;
import com.seeyon.cap4.template.util.CAPFormUtil;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.filemanager.manager.FileManager;
import com.seeyon.ctp.common.log.CtpLogFactory;
import com.seeyon.ctp.util.DateUtil;
import com.seeyon.ctp.util.ParamUtil;
import com.seeyon.ctp.util.StringUtil;
import com.seeyon.ctp.util.Strings;
import com.seeyon.ctp.util.annotation.RestInterfaceAnnotation;
import com.seeyon.ctp.util.json.JSONUtil;

/**
 * Created by weijh on 2018-6-7.
 * 自定义控件--表单转文档
 */
@Path("cap4/ocrCustom")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class OcrCustomResource extends BaseResource {
    private static final Log LOG = CtpLogFactory.getLog(OcrCustomResource.class);
    
    /**
     * 获取所有可以识别的证件类型
     *
     * @return
     */
    @GET
    @Path("ocrType")
    @RestInterfaceAnnotation(OpenExternal = RestInterfaceAnnotation.External.NO, StartVersion = "V7.0")
    public Response getOcrType() throws BusinessException {
        List<Map<String, Object>> types = new ArrayList<Map<String, Object>>();
        Map<String, Object> res = new HashMap<String, Object>();
        res.put("key", "identification_card_front");
        res.put("name", "身份证");
        types.add(res);
        return success(types);
    }

    /**
     * 获取当前表单能支持套红的主表字段列表
     *
     * @param formId           表单id
     * @param currentFieldName 当前字段名称
     * @return
     */
    @GET
    @Path("injectionFields")
    @RestInterfaceAnnotation(OpenExternal = RestInterfaceAnnotation.External.NO, StartVersion = "V7.0")
    public Response getInjectionFields(@QueryParam("formId") String formId, @QueryParam("currentFieldName") String currentFieldName) {
        CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");
        FormBean formBean = cap4FormManager.getEditingForm(Long.valueOf(formId));
        //只支持主表字段参与套红
        List<FormFieldBean> masterFields = formBean.getMasterTableBean().getFields();

        List<Map<String, Object>> resList = new ArrayList<Map<String, Object>>();
        for (FormFieldBean field : masterFields) {
            //排出当前字段名称
            if (field.getName().equalsIgnoreCase(currentFieldName)) {
                continue;
            }
            FormFieldCtrl ctrl = field.getFieldCtrl();
            //判断控件是否支持套红
            if (null != ctrl && ctrl.canInjectionWord()) {
                resList.add(field.getJsonObj4Design(false));
            }
        }
        for (FormTableBean subBean : formBean.getSubTableBean()) {
            for (FormFieldBean field : subBean.getFields()) {
                //排出当前字段名称
                if (field.getName().equalsIgnoreCase(currentFieldName)) {
                    continue;
                }
                FormFieldCtrl ctrl = field.getFieldCtrl();
                field.setDisplay("[" + subBean.getDisplay() + "]" + field.getDisplay());
                //判断控件是否支持套红
                if (null != ctrl && ctrl.canInjectionWord()) {
                    resList.add(field.getJsonObj4Design(false));
                }
            }
        }
        return success(resList);
    }

    /**
     * 获取当前ocr属性可以配置的表单字段
     *
     * @param formId
     * @param ocrSubProp
     * @param ocrType
     * @param currentField
     * @return
     */
    @GET
    @Path("formFields")
    @RestInterfaceAnnotation(OpenExternal = RestInterfaceAnnotation.External.NO, StartVersion = "V7.0")
    public Response getFormFields(@QueryParam("formId") String formId, @QueryParam("currentField") String currentField) {
        CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");
        FormBean formBean = cap4FormManager.getEditingForm(Long.valueOf(formId));
        FormTableBean currentTable = formBean.getFormTableBeanByFieldName(currentField);
        List<FormFieldBean> currentTableFields = currentTable.getFields();

        List<Map<String, Object>> resList = new ArrayList<Map<String, Object>>();
        for (FormFieldBean field : currentTableFields) {
            if (!field.isCustomerCtrl()) {
                resList.add(field.getJsonObj4Design(false));
            }
        }
        return success(resList);
    }

    /**
     * 根据ocr类型返回可以设置的属性
     *
     * @param type
     * @return
     */
    @GET
    @Path("fieldProperty")
    @RestInterfaceAnnotation(OpenExternal = RestInterfaceAnnotation.External.NO, StartVersion = "V7.0")
    public Response getFieldProperty() {
        List list = new ArrayList();
        list.add(new OrcVo("name", "姓名"));
        list.add(new OrcVo("sex", "性别"));
        list.add(new OrcVo("nationality", "民族"));
        list.add(new OrcVo("birth", "出生"));
        list.add(new OrcVo("address", "地址"));
        list.add(new OrcVo("id_number", "身份证号码"));
        list.add(new OrcVo("validate_date", "有效日期"));
        list.add(new OrcVo("issue_authority", "签发机构"));
        return success(list);
    }

    /**
     * 识别证件信息并返回数据
     *
     * @param formId    表单id
     * @param fieldName 字段名
     * @param fileId    附件id
     * @return
     * @throws BusinessException
     */
    @GET
    @Path("recognition")
    @RestInterfaceAnnotation(OpenExternal = RestInterfaceAnnotation.External.NO, StartVersion = "V7.0")
    @SuppressWarnings("unchecked")
    public Response recognition(@QueryParam("formId") String formId, @QueryParam("fieldName") String fieldName,
                                @QueryParam("fileId") String fileId, @QueryParam("formDataId") String formDataId,
                                @QueryParam("formSubDataId") String formSubDataId, @QueryParam("rightId") String rightId) throws BusinessException {
        CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");
        FormBean formBean = cap4FormManager.getForm(Long.parseLong(formId), false);
        FormFieldBean field = formBean.getFieldBeanByName(fieldName);

        FormDataMasterBean cacheFormData = cap4FormManager.getSessioMasterDataBean(Long.parseLong(formDataId));
        if (null == cacheFormData) {
            throw new BusinessException("表单数据在session中找不到（masterId:" + formDataId + "），请尝试重新打开。");
        }
        String name = "";
        FormDataSubBean formSubData = null;
        if (!field.isMasterField()) {
            formSubData = cacheFormData.getFormDataSubBeanById(field.getOwnerTableName(), Long.parseLong(formSubDataId));
            if (null == formSubData) {
                throw new BusinessException("OCR控件是明细表字段，但是通过明细表行id：" + formSubDataId + "找不到明细表数据");
            }
            name = (formSubData.getFieldValue(formBean.getFieldBeanByDisplay("姓名").getName()) == null
                    ? "" : formSubData.getFieldValue(formBean.getFieldBeanByDisplay("姓名").getName()).toString());
        } else {
            name = (cacheFormData.getFieldValue(formBean.getFieldBeanByDisplay("姓名").getName()) == null
                    ? "" : cacheFormData.getFieldValue(formBean.getFieldBeanByDisplay("姓名").getName()).toString());
        }

        String customParams = field.getCustomParam();
        Map<String, Object> define = (Map<String, Object>) JSONUtil.parseJSONString(customParams);
        Map<String, Object> mapping = (Map<String, Object>) define.get("mapping");
        if (mapping == null) {
            return success("No corresponding OCR settings");
        }

        List<Map<String, String>> ocrPropMapping = (List<Map<String, String>>) mapping.get("subPropMapping");
        List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
        Map<String, Object> data = getRecognition(name, fileId, ocrPropMapping);
        for (Map<String, String> defineMap : ocrPropMapping) {
            Map<String, Object> valueMap = new HashMap<String, Object>();
            String ocrKey = defineMap.get("source");
            String formFieldName = defineMap.get("target");

            if (Strings.isEmpty(ocrKey) || Strings.isEmpty(formFieldName)) {
                continue;
            }

            Object val = data.get(formFieldName);
            FormFieldBean formFieldBean = formBean.getFieldBeanByName(formFieldName);
            boolean isDate = FormFieldComEnum.EXTEND_DATE.getKey().equalsIgnoreCase(formFieldBean.getInputType());
            String formFieldValue = val == null ? null : String.valueOf(val);
            //如果是日期需要做转换转换成2018-7-11这种格式
            if (isDate && !StringUtil.checkNull(formFieldValue)) {
                val = formFieldValue.replaceAll("年|月", "-").replaceAll("日", "");
            }
            if (formFieldBean.isMasterField()) {
                cacheFormData.addFieldValue(formFieldName, val);
                val = cacheFormData.getFieldValue(formFieldName);
            } else {
                formSubData.addFieldValue(formFieldName, val);
                val = formSubData.getFieldValue(formFieldName);
            }
            Map<String, Object> tempRes = CAPFormUtil.getDisplayValueMap(val, formFieldBean, null);
            valueMap.put(formFieldName, tempRes);
            results.add(valueMap);
        }
        return success(results);
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> getRecognition(String name, String fileId,
                                               List<Map<String, String>> mapping) throws BusinessException {
        Map<String, Object> res = new HashMap<String, Object>();
        FileManager fileManager = (FileManager) AppContext.getBean("fileManager");
        File file = fileManager.getFile(Long.parseLong(fileId), DateUtil.currentDate());
        File compressFile = new File(file.getParentFile(), file.getName() + "_compress");
        try {
            ImgUtil.compress(file, compressFile);
        } catch (IOException e) {
            throw new BusinessException("图片压缩出错.");
        }

        String ret = HeheHttpUtil.sendOcrRequest(name, compressFile);
        if (ret != null) {
            Map map = JSONUtil.parseJSONString(ret, Map.class);
            if (map.containsKey("item_list")) {
                List<JSONObject> list = JSONUtil.parseJSONString(map.get("item_list").toString(), List.class);
                for (Map<String, String> params : mapping) {
                    String ocrKey = ParamUtil.getString(params, "source", "");
                    for (JSONObject obj : list) {
                        map = JSONUtil.parseJSONString(obj.toJSONString(), Map.class);
                        if (ParamUtil.getString(map, "key", "").equals(ocrKey)) {
                            res.put(ParamUtil.getString(params, "target"), ParamUtil.getString(map, "value", ""));
                            break;
                        }
                    }
                }
            }
        }
        return res;
    }

    @GET
    @Path("getToken")
    @RestInterfaceAnnotation(OpenExternal = RestInterfaceAnnotation.External.NO, StartVersion = "V7.0")
    public Response token() throws BusinessException {
        String ret = RestUtil.getInstence().getToken();
        return success(ret);
    }
}
